package com.lz.sports.bean

import android.os.Parcel
import android.os.Parcelable
import androidx.databinding.ObservableBoolean
import androidx.databinding.ObservableInt
import androidx.room.*
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.google.gson.JsonSerializationContext
import com.google.gson.JsonSerializer
import com.google.gson.annotations.Expose
import com.google.gson.annotations.SerializedName
import com.lz.helper.idcard.IDCardInfo
import com.lz.library.proguard.IProguardField
import com.lz.sports.ui.checkmodel.FeatureResult
import com.lz.sports.utils.DateUtils
import com.lz.sports.utils.UploadUtils
import com.lz.sports.utils.saveBitmapFile
import com.lz.sports.utils.saveNv21
import java.io.File
import java.lang.reflect.Type

//考试检录考生信息
@Entity(tableName = "ExamInspect", indices = [Index("inspectGroupId"), Index("examineeId")])
class ExamInspect() : Parcelable, IProguardField {

    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "examInspectId")
    var id: Int = 0

    //检录组ID
    @Expose
    @SerializedName("groupNumber")
    @ColumnInfo(name = "inspectGroupId")
    var inspectGroupId: Int = 0

    //考生ID
    @ColumnInfo(name = "examineeId")
    var examineeId: Int = 0

    //检录考试设备序号
    @ColumnInfo(name = "number")
    var number: Int = 0

    //考试计划ID
    @ColumnInfo(name = "examPlanId")
    var examPlanId: Int = 0

    //所属项目ID
    @ColumnInfo(name = "projectId")
    var projectId: Int = 0

    @ColumnInfo(name = "projectName")
    var projectName: String = ""

    //检录考区ID
    @ColumnInfo(name = "examAreaId")
    var examAreaId: Int = 0

    //检录的考点ID
    @ColumnInfo(name = "examSiteId")
    var examSiteId: Int = 0

    //检录时间
    @ColumnInfo(name = "inspectTime")
    var inspectTime: Long = 0L

    //当前检录考试成绩, -1未考
    @ColumnInfo(name = "score")
    var score: Int = 0

    //考试时间
    @ColumnInfo(name = "examTime")
    var examTime: Long = 0L

    //考试类型 9:JXN8-身份证-指纹-人脸（人照并人证)10:JXN9-身份证-人脸（人照并人证）-指纹
    @ColumnInfo(name = "examType")
    var examType: Int = 9

    //验证类型(通过)0人脸1指纹2手动
    @ColumnInfo(name = "verificationType")
    var verificationType: Int = -1

    //现场照片
    @ColumnInfo(name = "sceneImage")
    var sceneImage: String = ""

    //身份证照片
    @ColumnInfo(name = "cardImage")
    var cardImage: String = ""

    //报名照片
    @ColumnInfo(name = "photoImage")
    var photoImage: String = ""

    //身份证匹对结果
    @ColumnInfo(name = "idCardPhotoMate")
    var idCardPhotoMate: Float = 0f

    //报名照匹对结果
    @ColumnInfo(name = "examPhotoMate")
    var examPhotoMate: Float = 0f

    //指纹匹对结果
    @ColumnInfo(name = "fingerMate")
    var fingerMate: Float = 0f

    //验证是否通过：0未验证1通过2验证不通过3.存疑
    @ColumnInfo(name = "validateStatus")
    var validateStatus: Int = 0

    //现场照是否上传成功、
    @ColumnInfo(name = "scenePhotoUploadStatus")
    var scenePhotoUploadStatus = -1

    //身份证照否上传成功、
    @ColumnInfo(name = "idCardPhotoUploadStatus")
    var idCardPhotoUploadStatus = -1

    //报考照是否上传成功
    @ColumnInfo(name = "examPhotoUploadStatus")
    var examPhotoUploadStatus = -1

    //数据是否已经上传
    @ColumnInfo(name = "uploadStatus")
    var uploadStatus = -1

    //作为考试项时判断是否上传, 结合是否考试过了来判断
    @ColumnInfo(name = "examUploadStatus")
    var examUploadStatus = -1

    //对应的学生信息
    @Ignore
    var examinee: Examinee? = null

    //当前成绩
    @Ignore
    var result = ObservableInt(0)

    //是否连上线
    @Ignore
    var onLine = ObservableBoolean(false)

    //电量
    @Ignore
    var battery = ObservableInt(DeviceInfo.INIT_BATTERY)

    //拌绳数量
    @Ignore
    var mixing = ObservableInt(0)

    //开始时的模式是否已经初始化
    @Ignore
    var hasInitModel = false

    //是否为缺考
    fun isLack(): Boolean = examTime <= 0

    fun inspectTimeStr(): String = DateUtils.format(inspectTime)

    //考试时间
    fun examTimeStr(): String = DateUtils.format(examTime)

    //是否已经考试
    fun hasExamined(): Boolean = examTime > 0

    //身份证识别地址
    fun idCardImgFile(): File = File(UploadUtils.examInspectPath(), cardImage)

    //现场照地址
    fun sceneImgFile(): File = File(UploadUtils.examInspectPath(), sceneImage)

    //报名照地址
    fun examImgFile(): File = File(UploadUtils.examInspectPath(), photoImage)

    //检录到保存时将临时文件转移到正式文件目录下
    fun tmpRenameFile() {
        if (File(UploadUtils.examInspectTmpPath(), cardImage)
                .takeIf { it.exists() && it.isFile }?.renameTo(idCardImgFile()) != true
        ) {
            cardImage = ""
        }
        if (File(UploadUtils.examInspectTmpPath(), sceneImage)
                .takeIf { it.exists() && it.isFile }?.renameTo(sceneImgFile()) != true
        ) {
            sceneImage = ""
        }
        if (File(UploadUtils.examInspectTmpPath(), photoImage)
                .takeIf { it.exists() && it.isFile }?.renameTo(examImgFile()) != true
        ) {
            photoImage = ""
        }
    }

    fun initModel() {
        hasInitModel = true
    }

    fun saveResult(time: Long) {
        score = result.get()
        examTime = time
    }

    //重置
    fun reset() {
        onLine.set(false)
        battery.set(DeviceInfo.INIT_BATTERY)
        result.set(0)
        mixing.set(0)
        hasInitModel = false
    }

    //重置并绑定设备的状态
    fun reset(deviceInfo: DeviceInfo) {
        onLine.set(deviceInfo.isOnLine.get())
        battery.set(deviceInfo.battery.get())
        result.set(0)
        mixing.set(0)
        hasInitModel = false
    }

    //重考
    fun repeat() {
        result.set(0)
        mixing.set(0)
        hasInitModel = false
    }

    fun changeState(onLine: Boolean) {
        this.onLine.set(onLine)
    }

    //修改数据
    fun changeData(num: Int, battery: Int, mixing: Int) {
        if (!onLine.get()) onLine.set(true)
        this.result.set(num)
        this.battery.set(battery)
        this.mixing.set(mixing)
    }

    //更改电池电量
    fun changeBattery(battery: Int) {
        if (!onLine.get()) onLine.set(true)
        this.battery.set(battery)
    }

    fun isOnLine(): Boolean = onLine.get()

    //当不要在主线程中构造
    @Ignore
    constructor(examinee: Examinee, idCardInfo: IDCardInfo) : this() {
        this.examineeId = examinee.id
        this.examinee = examinee
        this.examType = CommonModel.ID_CARD
        val file = File(UploadUtils.examInspectTmpPath(), "card_${System.currentTimeMillis()}.jpg")
        idCardInfo.photoBitmap()?.also { saveBitmapFile(it, file.absolutePath, true) }
        cardImage = file.name
    }

    //当不要在主线程中构造
    @Ignore
    constructor(result: FeatureResult): this() {
        this.examineeId = result.examinee.id
        this.examinee = result.examinee
        verificationType = 0
        examType = result.type
        val sceneFile = File(UploadUtils.examInspectTmpPath(), "scene_${System.currentTimeMillis()}.jpg")
        saveNv21(result.nvData, result.w, result.h, sceneFile)
        sceneImage = sceneFile.name

        if (result.photoParams?.isSuccess() == true) {
            val cardFile = File(UploadUtils.examInspectTmpPath(), "card_${System.currentTimeMillis()}.jpg")
            saveBitmapFile(result.photoParams.bitmap, cardFile, false)
            cardImage = cardFile.name
            idCardPhotoMate = result.photoParams.thresholdResult
        }

        if (result.examParams?.isSuccess() == true) {
            val examFile = File(UploadUtils.examInspectTmpPath(), "exam_${System.currentTimeMillis()}.jpg")
            saveBitmapFile(result.examParams.bitmap, examFile, false)
            photoImage = examFile.name
            examPhotoMate = result.examParams.thresholdResult
        }
    }

    //检录
    fun inspect(inspectGroup: ExamInspectGroup) {
        this.inspectGroupId = inspectGroup.id
        this.examPlanId = inspectGroup.examPlanId
        this.projectId = inspectGroup.projectId
        this.projectName = inspectGroup.projectName
        this.examAreaId = inspectGroup.examAreaId
        this.examSiteId = inspectGroup.examSiteId
        this.inspectTime = inspectGroup.inspectTime
    }

    @Ignore
    constructor(parcel: Parcel) : this() {
        id = parcel.readInt()
        inspectGroupId = parcel.readInt()
        examineeId = parcel.readInt()
        number = parcel.readInt()
        examPlanId = parcel.readInt()
        projectId = parcel.readInt()
        projectName = parcel.readString()!!
        examAreaId = parcel.readInt()
        examSiteId = parcel.readInt()
        inspectTime = parcel.readLong()
        score = parcel.readInt()
        examTime = parcel.readLong()

        examType = parcel.readInt()
        verificationType = parcel.readInt()
        sceneImage = parcel.readString()!!
        cardImage = parcel.readString()!!
        photoImage = parcel.readString()!!
        idCardPhotoMate = parcel.readFloat()
        examPhotoMate = parcel.readFloat()
        fingerMate = parcel.readFloat()
        validateStatus = parcel.readInt()
        scenePhotoUploadStatus = parcel.readInt()
        idCardPhotoUploadStatus = parcel.readInt()
        examPhotoUploadStatus = parcel.readInt()
        uploadStatus = parcel.readInt()
        examUploadStatus = parcel.readInt()
    }

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeInt(id)
        parcel.writeInt(inspectGroupId)
        parcel.writeInt(examineeId)
        parcel.writeInt(number)
        parcel.writeInt(examPlanId)
        parcel.writeInt(projectId)
        parcel.writeString(projectName)
        parcel.writeInt(examAreaId)
        parcel.writeInt(examSiteId)
        parcel.writeLong(inspectTime)
        parcel.writeInt(score)
        parcel.writeLong(examTime)
        parcel.writeInt(examType)
        parcel.writeInt(verificationType)
        parcel.writeString(sceneImage)
        parcel.writeString(cardImage)
        parcel.writeString(photoImage)
        parcel.writeFloat(idCardPhotoMate)
        parcel.writeFloat(examPhotoMate)
        parcel.writeFloat(fingerMate)
        parcel.writeInt(validateStatus)
        parcel.writeInt(scenePhotoUploadStatus)
        parcel.writeInt(idCardPhotoUploadStatus)
        parcel.writeInt(examPhotoUploadStatus)
        parcel.writeInt(uploadStatus)
        parcel.writeInt(examUploadStatus)
    }

    companion object CREATOR : Parcelable.Creator<ExamInspect> {
        override fun createFromParcel(parcel: Parcel): ExamInspect {
            return ExamInspect(parcel)
        }

        override fun newArray(size: Int): Array<ExamInspect?> {
            return arrayOfNulls(size)
        }
    }

    override fun describeContents(): Int {
        return 0
    }

    override fun toString(): String {
        return "ExamInspect(id=$id, inspectGroupId=$inspectGroupId, examineeId=$examineeId, number=$number, examPlanId=$examPlanId, projectId=$projectId, projectName='$projectName', examAreaId=$examAreaId, examSiteId=$examSiteId, inspectTime=$inspectTime, score=$score, examTime=$examTime, examType=$examType, verificationType=$verificationType, sceneImage='$sceneImage', cardImage='$cardImage', photoImage='$photoImage', idCardPhotoMate=$idCardPhotoMate, examPhotoMate=$examPhotoMate, fingerMate=$fingerMate, validateStatus=$validateStatus, scenePhotoUploadStatus=$scenePhotoUploadStatus, idCardPhotoUploadStatus=$idCardPhotoUploadStatus, examPhotoUploadStatus=$examPhotoUploadStatus, uploadStatus=$uploadStatus, examUploadStatus=$examUploadStatus, examinee=$examinee, result=$result, onLine=$onLine, battery=$battery, mixing=$mixing, hasInitModel=$hasInitModel)"
    }


    class InspectSerializer : JsonSerializer<ExamInspect> {
        override fun serialize(src: ExamInspect, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement {
            val json = JsonObject()
            if (src.hasExamined()) {
                json.addProperty("studentId", src.examineeId)
                json.addProperty("examAreaId", src.examAreaId)
                json.addProperty("examPlanId", src.examPlanId)
                json.addProperty("examSiteId", src.examSiteId)
                json.addProperty("examProjectId", src.projectId)
                json.addProperty("groupNumber", src.inspectGroupId)
                json.addProperty("serialNumber", src.number)
                json.addProperty("examTime", DateUtils.format2(src.examTime))
                json.addProperty("scorce", src.score)

            } else {
                json.addProperty("studentId", src.examineeId)
                json.addProperty("examAreaId", src.examAreaId)
                json.addProperty("examPlanId", src.examPlanId)
                json.addProperty("examSiteId", src.examSiteId)
                json.addProperty("examProjectId", src.projectId)

                json.addProperty("examType", src.examType)
                json.addProperty("cardImage", src.cardImage)
                json.addProperty("groupNumber", src.inspectGroupId)
                json.addProperty("serialNumber", src.number)
                json.addProperty("fingerprintPercentage", src.fingerMate)
                json.addProperty("personPhotoPercentage", src.idCardPhotoMate)
                json.addProperty("sceneImage", src.sceneImage)
                json.addProperty("validateStatus", src.validateStatus)
                json.addProperty("verificationPercentage", src.validateStatus)
                json.addProperty("verificationType", src.verificationType)
                json.addProperty("verificationTime", DateUtils.format2(src.inspectTime))
            }
            return json
        }
    }

}